/**
 * @author Austin Andrews (Templarian)
 * @authorurl http://templarian.com
 * @framework DD Framework
 * @licence CC Attribution-No Derivative Works 2.0
 * @licenceurl http://creativecommons.org/licenses/by-nd/2.0/
 * @overview Scalable Vector Graphics Module
 */
dd.svg({
    init:function()
    {
        dd.extend({
            _svgStyle:function(o, s)
            {
                s = dd.is(s) ? s : {};
                // Handle basic styles
                for(var i in o)
                {
                    if(dd.is(o[i], "object") && s.hasOwnProperty(i))
                    {
                        for(var j in o[i])
                        {
                            if(s[i].hasOwnProperty(j))
                            {
                                o[i][j] = s[i][j];
                            }
                        }
                    }
                    else if(i in s)
                    {
                        o[i] = s[i];
                    }
                }
                // Handle overloads
                if("opacity" in s)
                {
                    if(dd.is(s.opacity, "number"))
                    {
                        o.stroke.opacity = s.opacity;
                        o.fill.opacity = s.opacity;
                    }
                }
                if("stroke" in s)
                {
                    if(dd.is(s.stroke, "number"))
                    {
                        o.stroke.width = s.stroke;
                    }
                    else if(dd.is(s.stroke, "string"))
                    {
                        o.stroke.color = s.stroke;
                    }
                }
                if("fill" in s)
                {
                    if(dd.is(s.fill, "string"))
                    {
                        o.fill.color = s.fill;
                    }
                }
                if("r" in s)
                {
                    if(dd.is(s.r, "number"))
                    {
                        o.r = {
                            x:s.r,
                            y:s.r
                        };
                    }
                }
            },
            _path:"",
            _obj:{
                path:"",
                log10:function(val) {
                    return Math.log(val) / Math.log(10);
                },
                f:function(num)
                {
                    if(num == 0)
                    {
                        return 0;
                    }
                    var d = Math.ceil(this.log10(num < 0 ? -num: num));
                    var power = 4 - d;
                    var magnitude = Math.pow(10, power);
                    var shifted = Math.round(num * magnitude);
                    return shifted / magnitude;
                },
                p:function(s)
                {
                    this.path += s;
                },
                moveTo:function(x, y)
                {
                    this.p("m" + x + "," + y);
                    return this;
                },
                lineTo:function(x, y)
                {
                    this.p("l" + x + "," + y);
                    return this;
                },
                curveTo:function()
                {
                    //x1 y1 x2 y2 x y
                    var a = arguments;
                    for(var i = 0; i < a.length;i += 6)
                    {
                        this.p("c" + this.f(a[i + 0]) + "," + this.f(a[i + 1]) + " "
                                   + this.f(a[i + 2]) + "," + this.f(a[i + 3]) + " "
                                   + this.f(a[i + 4]) + "," + this.f(a[i + 5]));
                    }
                    return this;
                },
                smoothTo:function()
                {
                    //x2 y2 x y
                    
                },
                close:function()
                {
                    this.p("z");
                    return this;
                }
            },
            moveTo:function(x, y)
            {
                this._obj.path = "";
                return this._obj.moveTo(x, y);
            }
        });
        dd.control("svg", function()
        {
            this.fn.parent = dd(this.parent).addElement({"svg":"svg"});
            this.method("addControl", dd.fn.addControl);
            this.method("addElement", (function(addElement, parent)
            {
                return function()
                {
                    return addElement.apply(parent, arguments);
                };
            })(this.parent.addElement, this.fn.parent));
            this.method("group", dd.svg._group);
            this.method("text", dd.svg._text);
            this.method("defs", dd.svg.defs);
            this.method("rect", dd.svg.rect);
            this.method("path", dd.svg.path);
        });
        // Not a real svg tag, completely for dev purposes
        dd.control("svg.region", function(o){
            this.fn.parent = dd(this.parent).addElement({"svg":"rect"}, {
                "x":0,
                "y":0,
                "width":o.width,
                "height":o.height,
                "fill":"#000",
                "style":"opacity:0.0;"
            });
            this.property("width", {
                get:function()
                {
                    return this.control.getAttribute("width");
                },
                set:function(v)
                {
                    this.control.setAttribute("width", v);
                    return v;
                }
            }, {control:this.fn.parent.self.e});
            this.property("height", {
                get:function()
                {
                    return this.control.getAttribute("height");
                },
                set:function(v)
                {
                    this.control.setAttribute("height", v);
                    return v;
                }
            }, {control:this.fn.parent.self.e});
        });
        dd.control("svg.g", function()
        {
            this.fn.parent = dd(this.parent).addElement({"svg":"g"}, {"style":""});
            this.method("style", dd.svg.style);
            this.method("matrix", dd.svg.matrix);
            this.method("translate", dd.svg.translate);
            this.property("x", {
                get:function()
                {
                    return parseInt(this.self.e.getAttribute("transform").match(/\((\d+)/)[1]);
                },
                set:function(v)
                {
                    var y = this.self.e.getAttribute("transform").match(/(\d+)\)/)[1];
                    this.self.e.setAttribute("transform", "translate(" + v + "," + y + ")");
                    return v;
                }
            }, this.fn.parent);
            this.property("y", {
                get:function()
                {
                    return this.self.e.getAttribute("transform");
                },
                set:function(v)
                {
                    return dd(this).text = v;
                }
            }, this.fn.parent);
            this.method("scale", dd.svg.scale);
            this.method("rotate", dd.svg.rotate);
            this.method("skewX", dd.svg.skewX);
            this.method("skewY", dd.svg.skewY);
            this.method("region", dd.svg._region);
            this.method("group", dd.svg._group);
            this.method("text", dd.svg._text);
            this.method("rect", dd.svg._rect);
            this.method("path", dd.svg._path);
            this.method("circle", dd.svg._circle);
            this.method("ellipse", dd.svg._ellipse);
        });
        dd.control("svg.rect", function()
        {
            this.fn.parent = dd.svg.rect.apply(this, arguments);
            this.method("style", dd.svg.style);
            this.method("hide", dd.svg.hide);
            this.method("show", dd.svg.show);
        });
        dd.control("svg.text", function()
        {
            this.fn.parent = dd.svg.text.apply(this, arguments);
            this.method("style", dd.svg.style);
            this.method("hide", dd.svg.hide);
            this.method("show", dd.svg.show);
            this.method("getCharNumAtPosition", dd.svg.getCharNumAtPosition);
            this.property("text", {
                get:function()
                {
                    return dd(this).text;
                },
                set:function(v)
                {
                    return dd(this).text = v;
                }
            }, this.fn.parent);
        });
    },
    _group:function()
    {
        return dd(this).addControl("svg.g");
    },
    _path:function(o, s)
    {
        return dd(this.parent).addControl("svg.path", o, s);
    },
    path:function(o, s)
    {
        var p = dd.isString(o) ? o : o.path;
        var e = {
            "x":0,
            "y":0,
            "opacity":1,
            "stroke":{
                "color":"#000",
                "width":1,
                "linecap":"butt",
                "opacity":1,
                "miterlimit":4
            },
            "fill":{}
        };
        if(dd.is("stroke", s))
        {
            if(dd.is("width", s.stroke))
            {
                e.stroke.width = s.stroke.width;
            }
            if(dd.is("color", s.stroke))
            {
                e.stroke.color = s.stroke.color;
            }
        }
        return dd(this.parent).addElement({"svg":"path"}, {
            "d":p,
            "style":"opacity:1;"
                   +"fill:none;"
                   +"stroke:" + e.stroke.color + ";"
                   +"stroke-width:" + e.stroke.width + ";"
                   +"stroke-linecap:butt;"
                   +"stroke-miterlimit:4;"
                   +"stroke-opacity:1"
        });
    },
    getCharNumAtPosition:function(o)
    {
        var p = this.self.e.nearestViewportElement.createSVGPoint();
        p.x = o.x; p.y = o.y;
        return this.self.e.getCharNumAtPosition(p);//getStartPositionOfChar
    },
    hide:function()
    {
        this.style("display", "none");
    },
    show:function()
    {
        this.style("display", "");
    },
    translate:function(o)
    {
        this.self.e.setAttribute("transform", "translate(" + o.x + "," + o.y + ")");
    },
    style:function(o1, o2)
    {
        if(dd.is(o2))
        {
            if(o1 == "x" || o1 == "y" || o1 == "width" || o1 == "height")
            {
                this.self.e.setAttribute(o1, o2);
                /*if("shadow" in this.parent)
                {
                    this.parent.shadow.e.setAttribute(o1, o2 + 1);
                }*/
            }
            else if(o1 == "shadow")
            {
                dd.svg.style.call({parent:this.parent.shadow}, "fill", o2);
            }
            else
            {
                if(this.self.e.getAttribute("style") == null)
                {
                    this.self.e.setAttribute("style", " ");
                }
                this.self.e.setAttribute("style",
                this.self.e.getAttribute("style")
                             .replace(new RegExp(o1 + ':[^;]+;'), "")
                + o1 + ":" + o2 + ";");
            }
            return this;
        }
        else if(dd.is(o1, "object"))
        {
            for(var i in o1)
            {
                this.style(i, o1[i]);
            }
            return this;
        }
        else
        {
            var r = new RegExp(o1 + ':([^;]+);');
            var m = r.exec(this.self.e.getAttribute("style"));
            return m === null ? "" : dd.trim(m[1]);
        }
    },
    // Overwrite for debugger.
    _region:function(o)
    {
        return dd(this).addControl("svg.region", o);
    },
    _text:function(text, o)
    {
        return dd(this).addControl("svg.text", text, o);
    },
    text:function(text, o)
    {
        var p = text.split(/\r?\n/);
        var e = {
            "x":0,
            "y":0,
            "shadow":"transparent",
            "textAnchor":"left",
            "stroke":{
                "opacity":1,
                "color":"none"
            },
            "fill":{
                "opacity":1,
                "color":"none"
            },
            "font":{
                "size":12,
                "weight":"normal",
                "style":"normal",
                "family":"Verdana"
            }
        };
        dd._svgStyle(e, o);
        if(o.shadow != "transparent" && p.length == 1)
        {
            var s = dd(this.parent).addElement({"svg":"text"}, text, {
                "x":e.x,
                "y":e.y + 1,
                "space": "preserve",
                "style":"text-anchor:" + e.textAnchor + ";"
                        + "fill:" + e.shadow + ";"
                        + "font-size:" + e.font.size + "px;"
                        + "fill-opacity:" + e.fill.opacity + ";"
                        + "font-weight" + e.font.weight + ";"
                        + "font-style:" + e.font.style + ";"
                        + "font-family:" + e.font.family + ";"
                        + "-moz-user-select:none;"
                        + "-webkit-user-select:none;"
                        + "user-select:none;"
            });
        }
        var style = "text-anchor:" + e.textAnchor + ";"
                    + "fill:" + e.fill.color + ";"
                    + "stroke:" + e.stroke.color + ";"
                    + "font-size:" + e.font.size + "px;"
                    + "fill-opacity:" + e.fill.opacity + ";"
                    + "font-weight" + e.font.weight + ";"
                    + "font-style:" + e.font.style + ";"
                    + "font-family:" + e.font.family + ";"
                    + "-moz-user-select:none;"
                    + "-webkit-user-select:none;"
                    + "user-select:none;";
        if(p.length == 1)
        {
            var t = dd(this.parent).addElement({"svg":"text"}, text, {
                "x":e.x,
                "y":e.y,
                "space": "preserve",
                "style":style
            });
            t.shadow = s;
        }
        else
        {
            var t = dd(this.parent).addElement({"svg":"text"}, {
                x:0,
                y:0,
                style:style
            });
            for(var i in p)
            {
                dd(t).addElement({"svg":"tspan"}, p[i], {
                    x:o.x,
                    y:o.y + (18 * i)
                });
            }
        }
        return t;
    },
    defs:function(o)
    {
        if(dd.is("linearGradient", o))
        {
            for(var i in o.linearGradient)
            {
                var lg = this.addElement({"svg":"linearGradient"}, {
                    "x1":o.linearGradient[i].x1,
                    "y1":o.linearGradient[i].y1,
                    "x2":o.linearGradient[i].x2,
                    "y2":o.linearGradient[i].y2,
                    "id":i
                });
                for(var j = 0; j < o.linearGradient[i].stop.length; j++)
                {
                    dd(lg).addElement({"svg":"stop"}, {
                        "style":"stop-color:" + o.linearGradient[i].stop[j].color + ";"
                               +"stop-opacity:1",
                        "offset":"offset" in o.linearGradient[i].stop[j]
                            ? o.linearGradient[i].stop[j].offset
                            : j
                    });
                }
            }
        }
    },
    _rect:function(o1, o2, o3, o4, o5)
    {
        return dd(this).addControl("svg.rect", o1, o2, o3, o4, o5);
    },
    rect:function(o1, o2, o3, o4, o5)
    {
        var e = {
            "x":0,
            "y":0,
            "width":10,
            "height":10,
            "stroke":{
                "color":"none",
                "width":1,
                "linecap":"butt",
                "opacity":1,
                "miterlimit":4
            },
            "fill":{
                "color":"none",
                "opacity":1
            },
            "r":{
                "x":0,
                "y":0
            }
        };
        if(dd.is(o5))
        {
            e.x = o1;
            e.y = o2;
            e.width = o3;
            e.height = o4;
            dd._svgStyle(e, o5);
        }
        else
        {
            dd._svgStyle(e, o1);
        }
        e.stroke.width = e.stroke.color == "none" ? 0 : e.stroke.width;
        return dd(this.parent).addElement({"svg":"rect"}, {
            "width":e.width - e.stroke.width,
            "height":e.height - e.stroke.width,
            "ry":e.r.y,
            "rx":e.r.x,
            "x":e.x,
            "y":e.y,
            "style":(e.fill.color == "none"
                    ? "fill:none;"
                    : "fill:" + e.fill.color + ";"
                     +"fill-opacity:" + e.fill.opacity + ";")
                   +(e.stroke.color == "none"
                    ? "stroke:none;"
                    : "stroke:" + e.stroke.color + ";"
                     +"stroke-width:" + e.stroke.width + "px;"
                     +"stroke-linecap:butt;"
                     +"stroke-linejoin:miter;"
                     +"stroke-opacity:" + e.stroke.opacity + ";")
        });
    }
});